package com.rockcent.mall.lib.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.SQLListDoing;
import com.rockcent.common.common.SQLObjectDoing;
import com.rockcent.common.common.SQLPageDoing;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.mall.lib.domain.Merchant;
import com.rockcent.mall.lib.domain.MerchantGiftPacket;
import com.rockcent.mall.lib.domain.enumclass.GiftPacketProductType;
import com.rockcent.mall.lib.domain.enumclass.GiftPacketStatus;
import com.rockcent.mall.lib.dto.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.List;

/**
 * Created by DK on 16/10/9.
 */
@Repository
public class MerchantGiftPacketRepositoryImpl implements MerchantGiftPacketRepositoryCustom{

    private static final Logger log = LoggerFactory.getLogger(MerchantGiftPacketRepositoryImpl.class);

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public PageResult<GiftPacketDto> findGiftPacketPage(Long merchantId, String status, String keyword, PageResult pageResult) {
        SQLPageDoing<GiftPacketDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from gift_packet gp where 1=1 ");
            if (StringUtils.isNotBlank(keyword)){
                sql.append(" AND (gp.id =:key  OR gp.name  LIKE :keyword)");
                params.put("key", keyword);
                params.put("keyword", "%" + keyword + "%");
            }
            sql.append(" AND gp.merchant_id =:merchantId");
            if (GiftPacketStatus.ALL == GiftPacketStatus.valueOf(status)) {
                sql.append(" AND gp.status in (:status)");
                params.put("status", Arrays.asList(GiftPacketStatus.S2_SELLING.toString(), GiftPacketStatus.S4_SOLDOUT.toString()));
            } else {
                sql.append(" AND gp.status = :status");
                params.put("status", status);
            }
            sql.append(" AND gp.is_delete = :isDelete");
            params.put("isDelete", Whether.NO.toString());
            params.put("merchantId", merchantId);
            if (GiftPacketStatus.S2_SELLING == GiftPacketStatus.valueOf(status)){
                sql.append( " order by gp.date_enabled desc ");
            }
            if (GiftPacketStatus.S5_FINISHED == GiftPacketStatus.valueOf(status)){
                sql.append( " order by gp.date_disabled desc ");
            }
            if (GiftPacketStatus.S6_UNSTART == GiftPacketStatus.valueOf(status)){
                sql.append( " order by gp.date_created desc ");
            }
            if (GiftPacketStatus.S1_DRAFTED == GiftPacketStatus.valueOf(status)){
                sql.append( " order by gp.date_created desc ");
            }
            if (GiftPacketStatus.ALL == GiftPacketStatus.valueOf(status)) {
                sql.append( " order by gp.date_created desc ");
            }
            fields.append("gp.*");
        };

        return doing.go(pageResult, GiftPacketDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public List<MerchantGiftPacketProductDto> findGiftPacketProduct(Long giftPacketId, GiftPacketProductType giftPacketProductType) {
        SQLListDoing<MerchantGiftPacketProductDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from gift_packet_products gpp left join product p on gpp.product_id = p.id left join product_quantity pq on p.product_quantity_id = pq.id where 1=1");
            sql.append(" AND gpp.gift_packet_product_type = :giftPacketProductType");
            sql.append(" AND gpp.packet_id = :giftPacketId");
            params.put("giftPacketId",giftPacketId);
            params.put("giftPacketProductType",giftPacketProductType.toString());
            fields.append("p.id productId,p.merchant_id merchantId, p.name,p.merchant_name merchantName,p.logo_url logoUrl,gpp.market_id marketId, gpp.market_merchant_id marketMerchantId, p.sell_price sellPrice,p.resell_fee resellFee,pq.quantity,gpp.packet_price packetPrice,gpp.use_number useNumber");
        };
        return doing.go(MerchantGiftPacketProductDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public List<MerchantGiftPacketCouponDto> findMerchantCouponList(Long giftPacketId) {
        SQLListDoing<MerchantGiftPacketCouponDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from gift_packet_coupons gpc left join coupon c on gpc.coupon_id = c .id left join merchant m on gpc.merchant_id = m.id where 1=1");
            sql.append(" AND gpc.packet_id = :giftPacketId");
            params.put("giftPacketId",giftPacketId);
            fields.append("c.id couponId,gpc.merchant_id,c.name,m.name as merchantName,c.use_scope useScope,c.logo_url logoUrl,c.leave_total leaveTotal,c.type,c.introduction,gpc.use_number useNumber");
        };
        return doing.go(MerchantGiftPacketCouponDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public PageResult<GiftPacketDto> findRelatedGiftPacket(Long merchantId, String keyword, String status, Long relateMerchantId, PageResult pageResult) {
        SQLPageDoing<GiftPacketDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from (select gpp.packet_id from gift_packet_products  gpp left join product p on gpp.market_id = p.id where gpp.market_merchant_id = :merId group by gpp.packet_id) relateGiftPacket " +
                    "left join gift_packet gp on relateGiftPacket.packet_id = gp.id where 1=1 ");

            if (StringUtils.isNotBlank(keyword)) {
                sql.append(" AND (gp.id =:key  OR gp.name  LIKE :keyword)");
                params.put("key", keyword);
                params.put("keyword", "%" + keyword + "%");
            }


            if (GiftPacketStatus.ALL == GiftPacketStatus.valueOf(status)) {
                sql.append(" and gp.status in (:status)");
                params.put("status", Arrays.asList(GiftPacketStatus.S2_SELLING.toString(), GiftPacketStatus.S4_SOLDOUT.toString(), GiftPacketStatus.S5_FINISHED.toString(), GiftPacketStatus.S6_UNSTART.toString()));
            }else if (GiftPacketStatus.S5_FINISHED == GiftPacketStatus.valueOf(status)){
                sql.append(" and gp.status in (:status)");
                params.put("status", Arrays.asList(GiftPacketStatus.S4_SOLDOUT.toString(), GiftPacketStatus.S5_FINISHED.toString()));
            }else {
                sql.append(" and gp.status = :status");
                params.put("status",status);
            }

            if (relateMerchantId != null){
                sql.append(" and gp.merchant_id = :relateMerchantId");
                params.put("relateMerchantId",relateMerchantId);
            }
            sql.append(" and gp.merchant_id != :merId");
            params.put("merId", merchantId);
            sql.append( " order by gp.date_created desc ");
            fields.append("gp.*");
        };
        return doing.go(pageResult, GiftPacketDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public List<Merchant> findGiftPacketMerchant(Long mallId, Long merchantId) {
        SQLListDoing<Merchant> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from gift_packet gp left join merchant m on gp.merchant_id = m.id where 1=1");
            sql.append(" AND gp.mall_id = :mallId");
            sql.append(" AND gp.merchant_id != :merchantId");
            sql.append(" AND gp.is_recommend = 1");
            sql.append(" and gp.status in (:status)");
            params.put("mallId",mallId);
            params.put("merchantId",merchantId);
            params.put("status", Arrays.asList(GiftPacketStatus.S2_SELLING.toString(), GiftPacketStatus.S4_SOLDOUT.toString(), GiftPacketStatus.S5_FINISHED.toString(), GiftPacketStatus.S6_UNSTART.toString()));
            sql.append(" group by gp.merchant_id");
            fields.append("m.id, m.name");
        };
        return doing.go(Merchant.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public PageResult<GiftPacketDto> findMarketGiftPacketPage(String sort, String sortByName, String keyword, String showSaleGiftPacket, Long mallId, Long merchantId, PageResult pageResult) {
        SQLPageDoing<GiftPacketDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from market_merchant_gift_packet mgp left join gift_packet gp on mgp.packet_id = gp.id where 1=1 ");
            if (StringUtils.isNotBlank(keyword)) {
                sql.append(" AND (gp.id =:key OR gp.name  LIKE :keyword OR gp.merchant_name like :keyword)");
                params.put("key", keyword);
                params.put("keyword", "%" + keyword + "%");
            }

            if (StringUtils.isNotBlank(showSaleGiftPacket)) {
                sql.append(" AND mgp.merchant_id != :merchantId");
            }
            sql.append(" and mgp.mall_id = :mallId");
            sql.append(" and gp.status in (:status)");
            params.put("mallId",mallId);
            params.put("status", Arrays.asList(GiftPacketStatus.S2_SELLING.toString(), GiftPacketStatus.S4_SOLDOUT.toString(), GiftPacketStatus.S5_FINISHED.toString(), GiftPacketStatus.S6_UNSTART.toString()));
            params.put("merchantId", merchantId);
            params.put("isDelete", Whether.NO.toString());
            if (StringUtils.isNotBlank(sortByName)) {
                sql.append(" order by gp.").append(sortByName).append(" ").append(sort);
            }
            fields.append("gp.*,(select ps.packet_id from market_merchant_gift_packet_sales ps where ps.distributor_merchant_id =:merchantId and ps.packet_id = mgp.packet_id and ps.is_delete = :isDelete) isSale ");
        };
        return doing.go(pageResult, GiftPacketDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public PageResult<GiftPacketDto> findMallGiftPacketPage(Long mallId, PageResult pageResult) {
        SQLPageDoing<GiftPacketDto> doing = (sql, fields, params, typeReferenceMap) ->{
            sql.append("select %s from gift_packet gp where 1=1");
            sql.append(" and gp.status in (:status)");
            sql.append(" and gp.date_disabled > now()");
            sql.append(" and gp.mall_id = :mallId");
            sql.append(" and gp.market_id is null ");
            params.put("mallId",mallId);
            params.put("status", Arrays.asList(GiftPacketStatus.S2_SELLING.toString(), GiftPacketStatus.S6_UNSTART.toString()));

            sql.append(" order by gp.date_created desc");
            fields.append("gp.*");
        };
        return doing.go(pageResult, GiftPacketDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public PageResult<GiftPacketDto> merchantGiftPacketPage(Long mallId, Long merchantId,List<Long> idList, PageResult pageResult) {
        SQLPageDoing<GiftPacketDto> doing = (sql, fields, params, typeReferenceMap) ->{
            sql.append("select %s from gift_packet gp where 1=1");
            sql.append(" and gp.mall_id = :mallId");
            sql.append(" and gp.merchant_id = :merchantId");
            if (idList != null){
                sql.append(" and gp.id in(:idList) ");
                params.put("idList",idList);
            }
            sql.append(" and gp.status in (:status)");
            params.put("mallId",mallId);
            params.put("merchantId",merchantId);
            params.put("status", Arrays.asList(GiftPacketStatus.S2_SELLING.toString(), GiftPacketStatus.S6_UNSTART.toString()));
            sql.append(" order by gp.date_created desc");
            fields.append("gp.*");
        };
        return doing.go(pageResult, GiftPacketDto.class, objectMapper, jdbcTemplate, log);
    }
    @Override
    public PageResult<MerchantGiftPacket> findByIdsPage(List<Long> giftPacketId, PageResult pageResult){
        SQLPageDoing<MerchantGiftPacket> doing = (sql, fields, params, typeReferenceMap) ->{
            sql.append("select %s from gift_packet gp where 1=1 ");
            if (giftPacketId != null && giftPacketId.size() > 0){
                sql.append(" and gp.id in(:giftPacketId) ");
                params.put("giftPacketId",giftPacketId);
            }
            sql.append(" and gp.status = \"S2_SELLING\" and gp.is_delete = \"NO\" ");
            fields.append("gp.*");
        };
        return doing.go(pageResult, MerchantGiftPacket.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public Long getGiftPacketCount(Long mallId, Long merchantId) {
        SQLObjectDoing<Long> doing=(sql, fields, params, typeReferenceMap) ->{

            sql.append("select %s from gift_packet gp where gp.is_delete='NO'");
            sql.append(" and gp.mall_id=:mallId");
            sql.append(" and gp.merchant_id=:merchantId");
            sql.append(" and gp.status=:status");

            params.put("status",GiftPacketStatus.S2_SELLING.toString());
            params.put("mallId",mallId);
            params.put("merchantId",merchantId);
            fields.append("count(1)");
        };
        return doing.go(Long.class,jdbcTemplate,log,objectMapper);

    }

    @Override
    public List<MerchantGiftPacket> getGiftPacketExpired() {
        SQLListDoing<MerchantGiftPacket> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from gift_packet gp where 1=1");
            sql.append(" and now() > gp.date_disabled");
            sql.append(" and gp.status != 'S5_FINISHED'");
            fields.append("gp.*");
        };
        return doing.go(MerchantGiftPacket.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public List<MerchantGiftPacket> getGiftPacketNotStart() {
        SQLListDoing<MerchantGiftPacket> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from gift_packet gp where 1=1");
            sql.append(" and now() >= gp.date_enabled");
            sql.append(" and gp.status = 'S6_UNSTART'");
            fields.append("gp.*");
        };
        return doing.go(MerchantGiftPacket.class, objectMapper, jdbcTemplate, log);
    }
}
